unit Category;

interface

uses
  GlobalRecordsAndEnums;

type
  TGroup = class;
  TSubcategory = class;

  TCategory = class
    private
      _id: Integer;
      _name: String[50];
      _subcategories: array of TSubcategory;

      function GetName: String;
      function GetSubcategoryCount: Integer;
    public
      constructor Create(name: String; id: Integer); overload;
      constructor Create(cat: SCategory); overload;
      destructor Destroy; reintroduce;

      procedure AddSubcategory(subcat: TSubcategory);
      function GetSubcategory(index: Integer): TSubcategory;
      procedure RemoveSubcategory(subcat: TSubCategory);

      property Name: String read GetName;
      property ID: Integer read _id;
      property SubcategoryCount: Integer read GetSubcategoryCount;
  end;

  TSubcategory = class
    private
      _id: Integer;
      _name: String[50];
      _category: TCategory;
      _groups: array of TGroup;

      function GetName: String;
      function GetGroupCount: Integer;
    public
      constructor Create(name: String; id: Integer; category: TCategory); overload;
      constructor Create(subcat: SSubcategory; category: TCategory); overload;
      destructor Destroy; reintroduce;

      procedure AddGroup(group: TGroup);
      function GetGroup(index: Integer): TGroup;
      procedure RemoveGroup(group: TGroup);

      property Name: String read GetName;
      property ID: Integer read _id;
      property Category: TCategory read _category;
      property GroupCount: Integer read GetGroupCount;
  end;

  TGroup = class
    private
      _id: Integer;
      _name: String[50];
      _subcategory: TSubCategory;

      function GetName: String;
    public
      constructor Create(name: String; id: Integer; subcategory: TSubcategory); overload;
      constructor Create(grp: SGroup; subcategory: TSubCategory); overload;
      destructor Destroy; reintroduce;

      property Name: String read GetName;
      property ID: Integer read _id;
      property Subcategory: TSubCategory read _subcategory;
  end;

implementation

//=========================================
//=============== TCategory ===============
//=========================================
constructor TCategory.Create(name: String; id: Integer);
begin
  Inherited Create;
  self._id := id;
  self._name := name;
end;

constructor TCategory.Create(cat: SCategory);
begin
  self.Create(cat.Name, cat.ID);
end;

destructor TCategory.Destroy;
begin
  Inherited Destroy;
end;

function TCategory.GetName: String;
begin
  result := String(_name);
end;

function TCategory.GetSubcategoryCount: Integer;
begin
  result := Length(_subcategories);
end;

procedure TCategory.AddSubcategory(subcat: TSubCategory);
var
  len: Integer;
begin
  len := Length(_subcategories);
  SetLength(_subcategories, len +1);
  _subcategories[len] := subcat;
end;

function TCategory.GetSubcategory(index: Integer): TSubcategory;
begin
  if (index >= Length(_subcategories)) then result := nil
  else result := _subcategories[index];
end;

procedure TCategory.RemoveSubcategory(subcat: TSubCategory);
var
  i, indextoremove: Integer;
begin
  indextoremove := -1;
  for i := 0 to Length(_subcategories) -1 do begin
    if (_subcategories[i].ID = subcat.ID) then indextoremove := i;
  end;
  if (indextoremove >= 0) then begin
    for i := indextoremove to Length(_subcategories) -2 do begin
      _subcategories[i] := _subcategories[i+1];
    end;
    SetLength(_subcategories, Length(_subcategories) -1);
  end;
end;

//============================================
//=============== TSubCategory ===============
//============================================
constructor TSubcategory.Create(name: String; id: Integer; category: TCategory);
begin
  Inherited Create;
  self._id := id;
  self._name := name;
  self._category := category;
  self._category.AddSubcategory(self);
end;

constructor TSubcategory.Create(subcat: SSubcategory; category: TCategory);
begin
  self.Create(subcat.Name, subcat.ID, category);
end;

destructor TSubcategory.Destroy;
begin
  Inherited Destroy;
end;

function TSubCategory.GetName: String;
begin
  result := String(_name);
end;

function TSubcategory.GetGroupCount: Integer;
begin
  result := Length(_groups);
end;

procedure TSubcategory.AddGroup(group: TGroup);
var
  len: Integer;
begin
  len := Length(_groups);
  SetLength(_groups, len +1);
  _groups[len] := group;
end;

function TSubcategory.GetGroup(index: Integer): TGroup;
begin
  if (index >= Length(_groups)) then result := nil
  else result := _groups[index];
end;

procedure TSubcategory.RemoveGroup(group: TGroup);
var
  i, indextoremove: Integer;
begin
  indextoremove := -1;
  for i := 0 to Length(_groups) -1 do begin
    if (_groups[i].ID = group.ID) then indextoremove := i;
  end;
  if (indextoremove >= 0) then begin
    for i := indextoremove to Length(_groups) -2 do begin
      _groups[i] := _groups[i+1];
    end;
    SetLength(_groups, Length(_groups) -1);
  end;
end;

//======================================
//=============== TGroup ===============
//======================================
constructor TGroup.Create(name: String; id: Integer; subcategory: TSubCategory);
begin
  Inherited Create;
  self._id := id;
  self._name := name;
  self._subcategory := subcategory;
  self._subcategory.AddGroup(self);
end;

constructor TGroup.Create(grp: SGroup; subcategory: TSubCategory);
begin
  self.Create(grp.Name, grp.ID, subcategory);
end;

destructor TGroup.Destroy;
begin
  Inherited Destroy;
end;

function TGroup.GetName: String;
begin
  result := String(_name);
end;


end.

